const AlchemyWeb3 = require('@alch/alchemy-web3')
const _ = require('lodash')
const Tx = require('ethereumjs-tx').Transaction
const abiDecoder = require('abi-decoder')
const ethers = require('ethers') // Require the ethers library
const utils = require('ethers').utils
const config = require('./config.js')
let json = require('./abi.json')

abiDecoder.addABI(json)
const { spawn, exec } = require('child_process')

function getJSON() {
  console.log(json) // this will show the info it in firebug console
}
//私钥签名交易函数
async function signTx(web3, fields = {}) {
  const nonce = await web3.eth.getTransactionCount(config.fromAddress, 'latest')
  console.log('nonce', nonce)
  const transaction = {
    nonce: nonce,
    ...fields
  }

  return await web3.eth.accounts.signTransaction(transaction, config.privateKey)
}
//发送交易函数
async function sendTx(web3, fields = {}) {
  const signedTx = await signTx(web3, fields)

  web3.eth.sendSignedTransaction(signedTx.rawTransaction, function (error, hash) {
    if (!error) {
      console.log('Transaction sent!', hash)
      const interval = setInterval(function () {
        console.log('Attempting to get transaction receipt...')
        web3.eth.getTransactionReceipt(hash, function (err, rec) {
          if (rec) {
            console.log(rec)
            clearInterval(interval)
          }
        })
      }, 1000)
    } else {
      console.log('Something went wrong while submitting your transaction:', error)
    }
  })
}
//计算gas并签名发起交易函数
function sendMinimalLondonTx(web3, data, toAddress, price) {
  console.log('data', data, typeof data)
  web3.eth
    .estimateGas({
      from: config.fromAddress,
      data: data,
      to: toAddress,
      value: web3.utils.toWei(price, 'ether')
    })
    .then(estimatedGas => {
      console.log('estimatedGas', estimatedGas)
      sendTx(web3, {
        gas: estimatedGas,
        maxPriorityFeePerGas: web3.utils.toHex(web3.utils.toWei(config.maxPriorityFeePerGas, 'gwei')),
        maxFeePerGas: web3.utils.toHex(web3.utils.toWei(config.maxFeePerGas, 'gwei')),
        to: toAddress,
        value: web3.utils.toWei(price, 'ether'),
        data: web3.utils.toHex(data)
      })
    })
}

const pendingTrasactions = async () => {
  let web3URL
  let targetContract
  let creator
  //判断是否测试网
  console.log('Network Mode:', config.network)
  switch (config.network) {
    //---------------- TEST USAGE-------------------------
    case 'Rinkeby': {
      web3URL = config.wssRinkeby
      targetContract = ''
      creator = ''
      break
    }
    case 'Goerli': {
      web3URL = config.wssGoerli
      targetContract = ''
      creator = ''
      break
    }
    //-----------------------------------------------------
    default: {
      web3URL = config.wssMainnet
      targetContract = config.toAddress
      creator = config.creatorAddress
    }
  }

  console.log('Web3URL:', web3URL)
  const web3 = AlchemyWeb3.createAlchemyWeb3(web3URL)
  var contract = new web3.eth.Contract(json, targetContract)

  //-----------------------------------------------------------------
  //--------------- Change this function every time------------------
  let extraData = await contract.methods.mint(config.param[0])
  //-----------------------------------------------------------------
  //-----------------------------------------------------------------

  let data = extraData.encodeABI()

  // DEBUG SECTION
  //sendMinimalLondonTx(web3,data,targetContract,config.price);

  //监测合约何时发起代币/NFT公开销售
  web3.eth
    .subscribe('alchemy_filteredNewFullPendingTransactions', {
      address: targetContract.toLocaleLowerCase()
    })
    .on('data', async blockHeader => {
      const auther = blockHeader.from
      const decodedData = abiDecoder.decodeMethod(blockHeader.input)

      //如果合约管理员调用了发起公开销售的函数,即开始发送交易
      if (auther.toLowerCase() === creator.toLowerCase()) {
        if (decodedData) {
          //-----------------------------------------------------------------
          //--------------- Change this function every time------------------
          if (decodedData.name == 'XXX') {
            //-----------------------------------------------------------------
            //-----------------------------------------------------------------
            // your code
            console.log('Found out the public sales', decodedData.name)
            console.log('INPUT DATA', data)
            sendMinimalLondonTx(web3, data, targetContract, config.price)
          }
        }
      }
    })
}

pendingTrasactions()
